package st.base;

import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.TreeMap;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import st.BasicStockData;
import st.strategy.vo.Stock;

public class Sysdate {
	private Collection<BasicStockData> stockDatas;

	private Collection<Stock> stocks;

	public void addStockData(BasicStockData basicStockData) {
		stockDatas.add(basicStockData);
		stocks.add(basicStockData.getStock());
	}

	private Calendar delicate;
	public static final String KEY_DATE_PATERN = "yyyyMMdd";
	static Logger logger = LoggerFactory.getLogger(Sysdate.class);
	private int idx;
	private String _toString;

	public String getString() {
		return _toString;
	}

	public static void main(String[] args) {
		try {
			Sysdate calendar = Sysdate.getInstance("20030101");
			System.out.println(calendar);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private Sysdate() {
		stockDatas = new HashSet<BasicStockData>();
		stocks = new HashSet<Stock>();
	}

	public static Sysdate getInstance(String dateStr) {
		return SYSDATE_STR.get(dateStr);
	}

	public static Collection<Sysdate> getInstanceBetween(String start,
			String end) {
		return SYSDATE_STR.subMap(start, true, end, true).values();
	}

	/** key=yyyyMMdd, value 為對應Calendar */
	private static TreeMap<String, Sysdate> SYSDATE_STR;
	private static HashMap<Integer, Sysdate> SYSDATE_IDX;

	static {
		logger.info("載入日期檔");
		SYSDATE_STR = new TreeMap<String, Sysdate>();
		SYSDATE_IDX = new HashMap<Integer, Sysdate>();
		Calendar curCalendar = Calendar.getInstance();
		curCalendar.clear();
		curCalendar.set(1990, Calendar.JANUARY, 1);
		Calendar sysdate = Calendar.getInstance();
		// sysdate.add(Calendar.DATE, -2);
		int i = 0;
		while (sysdate.after(curCalendar)) {
			Sysdate s = new Sysdate();
			Calendar c = DateUtils.truncate(curCalendar, Calendar.DATE);
			curCalendar.add(Calendar.DATE, 1);
			s.delicate = c;
			s.idx = ++i;
			String dateStr = DateFormatUtils.format(c, KEY_DATE_PATERN);
			s._toString = dateStr;
			SYSDATE_STR.put(dateStr, s);
			SYSDATE_IDX.put(s.idx, s);
		}
		logger.info("載入{}天", i);
	}

	public boolean before(Sysdate when) {
		return delicate.before(when.delicate);
	}

	public boolean after(Sysdate when) {
		return delicate.after(when.delicate);
	}

	public boolean before(Calendar when) {
		return delicate.before(when);
	}

	public boolean after(Calendar when) {
		return delicate.after(when);
	}

	public Sysdate add(int amount) {
		return SYSDATE_IDX.get(idx + amount);
	}

	/** 取得stock下amount個交易日 */
	public Sysdate add(int amount, Stock stock) {
		int nextOffset;// 如果offsetSysdate沒有stockData資料時，往nextOffset再跳下一個交易日
		if (amount >= 0) {
			nextOffset = 1;
		} else {
			nextOffset = -1;
		}
		Sysdate offsetSysdate = SYSDATE_IDX.get(idx + amount);
		if (offsetSysdate == null) {
			logger.error("{}取不到{}日期", this, nextOffset);
			return null;
		}
		while (!offsetSysdate.stocks.contains(stock)) {
			offsetSysdate = offsetSysdate.add(nextOffset);
			if (offsetSysdate == null) {
				logger.error("{}取不到{}日期", this, nextOffset);
				return null;
			}
		}
		return offsetSysdate;
	}

	@Override
	public String toString() {
		return "Sysdate [_toString=" + _toString + "]";
	}
}
